home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / XCMDs and XFCNs / HCGestalt XFCN 1.1.1 / HCGestalt.c next >
Encoding:
C/C++ Source or Header  |  1994-05-06  |  7.8 KB  |  334 lines  |  [TEXT/R*ch]

  1. /****************************************************************************
  2. *
  3. *  HCGestalt XFCN v1.1.1
  4. *
  5. *  All source code © 1992-94 Best Before Yesterday (Alex Metcalf)
  6. *  All rights reserved
  7. *
  8. *
  9. *  This source code is being distributed to allow new programmers to
  10. *  see how to get started with writing an external for Hypercard.
  11. *  I know it's not perfect code (I'm sure people can suggest ways to
  12. *  optimize it), but I think it's a good example of how you can receive
  13. *  parameters, as well as return a result to Hypercard.
  14. *
  15. *  This code is for THINK C. Make a project, and include the files:
  16. *  "ANSI-A4", "HyperXLib", and "MacTraps". You'll probably need all three
  17. *  of these when you write your own external.
  18. *
  19. *  Please distribute only unmodified versions of this code.
  20. *  Contact me if you wish to use this XFCN in your stacks.
  21. *
  22. *  Alex Metcalf
  23. *  alex@metcalf.demon.co.uk
  24. *
  25. *  UK Fax:        (0570) 45636
  26. *  US/Canada Fax: 011 44 570 45636
  27. *
  28. ****************************************************************************/
  29.  
  30.  
  31. /*****
  32. *
  33. * A quick note about memory:
  34. *
  35. * The most common problem in Hypercard externals occurs when you don't
  36. * "tidy up after yourself". This means that you allocate some memory
  37. * somewhere, and then don't get rid of it when you leave. Not good! Although
  38. * this only causes problems when the user calls your XCMD lots of times,
  39. * it's much better to find the leak and plug it. The way to check for a
  40. * leak is to make an empty stack, put your XCMD or XFCN in the stack, and
  41. * put the following into the card script:
  42. *
  43. * on idle
  44. *    MyXCMD "parameter 1"
  45. *    put the heapspace
  46. * end idle
  47. *
  48. * or if it's an XFCN:
  49. *
  50. * on idle
  51. *    get MyXFCN "parameter 1"
  52. *    put the heapspace
  53. * end idle
  54. *
  55. * Then move the mouse over the button and watch the number in the msg box.
  56. * If it's going down, you have a memory leak! Check through your code for
  57. * any times you use NewPtr() or NewHandle(), and make sure you're disposing
  58. * them if you have to. I've only used NewPtr once in this code, and I didn't
  59. * dispose it because I'm giving it back to Hypercard. Another way you can
  60. * lose memory is if you use a toolbox routine which allocates memory, and
  61. * you don't bother to get rid of it.
  62. *
  63. *****/
  64.  
  65.  
  66. #include <HyperXCmd.h>
  67. #include <gestaltEqu.h>
  68.  
  69. /*****
  70. *
  71. * If you want to use global variables in your code, then you need
  72. * to include:
  73. *
  74. * #include <SetUpA4.h>
  75. *
  76. * Then, right at the beginning of main(), type in "SetUpA4 ();". Then, right
  77. * at the end of main(), type in "RestoreA4 ();". You'll then be able to use
  78. * global variables.
  79. *
  80. * Note you'll also need to put RestoreA4 right before any "return" commands
  81. * you have in your main().
  82. *****/
  83.  
  84.  
  85. /*****
  86. *
  87. * To return a result to Hypercard, you need to give Hypercard a handle
  88. * to a C string which you have made.
  89. *
  90. *****/
  91.  
  92. void ReturnValue (XCmdPtr paramPtr, char *tStringPtr)
  93. {
  94.     Handle    tStringHandle;
  95.     
  96.     tStringHandle = NewHandle (256);
  97.     if (tStringHandle == nil)
  98.     {
  99.         SysBeep (1);
  100.         return;
  101.     }
  102.     
  103.     MoveHHi (tStringHandle);
  104.     HLock (tStringHandle);
  105.     strcpy ((char *) *tStringHandle, tStringPtr);
  106.     
  107.     paramPtr->returnValue = tStringHandle;
  108. }
  109.  
  110. /*****
  111. *
  112. * UpperCase is a little routine I made to convert the user's parameters
  113. * into upper case. Otherwise, if they used a parameter "one" and you only
  114. * checked for "One", for example, they'd wonder why it wasn't working.
  115. *
  116. * I think there's a command in C for converting a string to upper case,
  117. * but I didn't know that when I wrote this. :-)
  118. *
  119. *****/
  120.  
  121. UpperCase (char *tString)
  122. {
  123.     short        i, tLength;
  124.     
  125.     tLength = strlen (tString);
  126.     for (i=0;i<=tLength;i++)
  127.     {
  128.         if ( (tString[i] >= 'a') && (tString[i] <= 'z') )
  129.         {
  130.             tString[i] -= 32;
  131.         }
  132.     }
  133. }
  134.  
  135.  
  136. /*****
  137. *
  138. * Great little piece of code to check for a system version you require.
  139. * For example, if your XCMD needs System 7.0.1 or later, replace the
  140. * 604 with 701. This XFCN, obviously, requires System 6.0.4 or later.
  141. *
  142. *****/
  143.  
  144.  
  145. Boolean SystemOK (void)
  146. {
  147.     OSErr         myStatus;
  148.     SysEnvRec    myEnvData;
  149.     
  150.     myStatus = SysEnvirons (1, &myEnvData);
  151.     if ((myStatus != noErr) ||
  152.         (myEnvData.systemVersion < 0x604))
  153.     {
  154.         return false;
  155.     } else
  156.     {
  157.         return true;
  158.     }
  159. }
  160.  
  161. /*****
  162. *
  163. * Used for checking for a Gestalt feature.
  164. *
  165. *****/
  166.  
  167. char * CheckMyBit (long *tFeature, short tTestBit)
  168. {
  169.     if (BitTst (tFeature, 31-tTestBit) == true)
  170.     {
  171.         return "true";
  172.     } else
  173.     {
  174.         return "false";
  175.     }
  176. }
  177.  
  178. /*****
  179. *
  180. * A small but very important bit of code, which reads in the parameters
  181. * that the programmer gives you. For the first parameter, use 'params[0]',
  182. * for the second use 'params[1]', and so on. You can check the number
  183. * of parameters that the user gave you by checking "paramPtr->paramCount".
  184. *
  185. *****/
  186.  
  187. void LoadParams (XCmdPtr paramPtr, char *tSelectorType)
  188. {
  189.     strcpy (tSelectorType, *(paramPtr->params[0]));
  190. }
  191.  
  192. /*****
  193. *
  194. * The majority of this code deals with the Gestalt Manager.
  195. * If you're only interested in the 'core' of the XCMD, skip
  196. * right down to the bottom, to main().
  197. *
  198. * I've removed most of the checks, but I've left one or two so you
  199. * get an idea of what's happening.
  200. *
  201. *****/
  202.  
  203. void HCGAddressingMode (char *tReturnStr)
  204. {
  205.     long    tFeature;
  206.     int        tError;
  207.     
  208.     tError = Gestalt (gestaltAddressingModeAttr, &tFeature);
  209.     if (tError != noErr)
  210.     {
  211.         strcpy (tReturnStr, "Error");
  212.         return;
  213.     }
  214.     strcpy (tReturnStr, CheckMyBit (&tFeature,
  215.         gestalt32BitAddressing));
  216.     
  217.     if (strcmp (tReturnStr, "true") == 0)
  218.     {
  219.         strcpy (tReturnStr, "32 Bit Addressing");
  220.     } else
  221.     {
  222.         strcpy (tReturnStr, "24 Bit Addressing");
  223.     }
  224. }
  225.  
  226. void HCGMachineType (char *tReturnStr)
  227. {
  228.     long    tFeature;
  229.     int        tError;
  230.     
  231.     tError = Gestalt (gestaltMachineType, &tFeature);
  232.     if (tError != noErr)
  233.     {
  234.         strcpy (tReturnStr, "Error");
  235.         return;
  236.     }
  237.     GetIndString ((StringPtr) tReturnStr,
  238.         kMachineNameStrID, tFeature);
  239.     PtoCstr ((StringPtr) tReturnStr);
  240. }
  241.  
  242. void HCGROMSize (char *tReturnStr)
  243. {
  244.     long    tFeature;
  245.     int        tError;
  246.     
  247.     tError = Gestalt (gestaltROMSize, &tFeature);
  248.     if (tError != noErr)
  249.     {
  250.         strcpy (tReturnStr, "Error");
  251.         return;
  252.     }
  253.     NumToString (tFeature, (StringPtr) tReturnStr);
  254.     PtoCstr ((StringPtr) tReturnStr);
  255. }
  256.  
  257. void GetGestalt (char *selector, char *tReturnStr)
  258. {
  259.     UpperCase (selector);
  260.     
  261.     if (strcmp (selector, "ADDRESSING MODE")==0)
  262.     {
  263.         HCGAddressingMode (tReturnStr);
  264.         return;
  265.     }
  266.     
  267.     if (strcmp (selector, "MACHINE TYPE")==0)
  268.     {
  269.         HCGMachineType (tReturnStr);
  270.         return;
  271.     }
  272.     
  273.     strcpy (tReturnStr, "Error: selector type unknown.");
  274. }
  275.  
  276. /*****
  277. *
  278. * main() is the first bit of code that is executed when the user calls your
  279. * external. The only parameter is something called an XCmdPtr: this is the
  280. * information that Hypercard passes you, such as what parameters the user
  281. * entered and stuff like that. Don't lose it! You need the same information
  282. * to give a result back to the user. If you want to know more about it,
  283. * look in the header "HyperXCmd.h".
  284. *
  285. * I've started by checking the system version to make sure Gestalt's available.
  286. * I then used paramPtr->paramCount to make sure that they only entered one
  287. * parameter: if they didn't, then I tell them how to do it properly! Then,
  288. * LoadParams () loads  the parameter, and GetGestalt goes away and figures
  289. * out what they want. If any of my Gestalt stuff returned an error message,
  290. * then I convert it to something more meaningful for the user. Finally, I
  291. * use ReturnValue to give the result back to the user. Simple!
  292. *
  293. *****/
  294.     
  295. pascal void main (XCmdPtr paramPtr)
  296. {
  297.     char    tReturnStr[256], selector[256];
  298.     
  299.     *tReturnStr = 0;
  300.     
  301.     if (!SystemOK ())
  302.     {
  303.         strcpy (tReturnStr, "Error: HCGestalt requires System 6.0.4"
  304.             " or later.");
  305.         ReturnValue (paramPtr, tReturnStr);
  306.         return;
  307.     }
  308.  
  309.     if ( !(paramPtr->paramCount==1) )
  310.     {
  311.         strcpy (tReturnStr, "Syntax: HCGestalt <selector type>");
  312.         ReturnValue (paramPtr, tReturnStr);
  313.         return;
  314.     }
  315.     
  316.     LoadParams (paramPtr, selector);
  317.     GetGestalt (selector, tReturnStr);
  318.     
  319.     if (strcmp(tReturnStr, "Error")==0)
  320.     {
  321.         strcpy (tReturnStr, "Error: Gestalt Manager returned"
  322.             " an error.");
  323.     }
  324.     
  325.     ReturnValue (paramPtr, tReturnStr);
  326. }
  327.  
  328. /*****
  329. *
  330. * The end!
  331. *
  332. *****/
  333.